﻿using System;
using System.Collections.Generic;
using System.Linq;
using Missbot.Common;
using Missbot.Core.Base;
using Missbot.Core.SyntaxChecker.ParamCheckers;
using Dolany.UtilityTool;
using JetBrains.Annotations;
using Missbot.AIModule.Base;
using Missbot.AIModule.OnlineStore;
using Missbot.AIModule.Pet;
using Missbot.AIModule.Vip;
using Missbot.Core.Cache;

namespace Missbot.AIModule.Gaming.DriftBottle
{
    [UsedImplicitly]
    public class DriftBottleMod : IAIModule
    {
        public override string Name => "漂流瓶";

        private const int ItemRate = 60;
        private const int PageSize = 7;

        public HonorSvc HonorSvc { get; set; }

        [ModuleEnter(Command = "捞瓶子", Description = "捞一个漂流瓶", DailyLimit = 3)]
        public bool FishingBottle(InboxSession session)
        {
            if (OSPersonBuffDA.CheckBuff(session.User.ID, "昙天"))
            {
                session.SendBack("你当前无法捞瓶子！(昙天)");
                return false;
            }

            if (Rander.RandInt(100) < ItemRate)
            {
                FishItem(session);
                return true;
            }

            var records = DriftBottleRecordDA.GetOthers(session.User.ID);
            if (records.IsNullOrEmpty())
            {
                FishItem(session);
                return true;
            }

            var bottle = records.RandElement();
            PrintBottle(session, bottle);

            bottle.ReceivedGroupID = session.Group?.ID;
            bottle.ReceivedUserID = session.User.ID;
            bottle.ReceivedTime = DateTime.Now;

            bottle.Update();
            return true;
        }

        private void FishItem(InboxSession session)
        {
            if (OSPersonBuffDA.CheckBuff(session.User.ID, "梅雨") && Rander.RandInt(100) < 30)
            {
                session.SendBack("欸呀呀，捞瓶子失败了！(梅雨)");
                return;
            }

            var item = HonorSvc.RandItem();
            var record = ItemCollectionDA.Get(session.User.ID);
            var honorName = HonorSvc.FindHonorName(item.Name);

            var count = 1;
            var vipArmers = VipArmerDA.Get(session.User.ID);
            if (vipArmers != null && vipArmers.CheckArmer("安妮的镜子"))
            {
                count = 2;
                vipArmers.Armers.Remove(p => p.Name == "安妮的镜子");
                vipArmers.Update();
            }

            DriftBottleAnalyzeDA.Record(item.Name, count);

            var s = record.ItemIncome(item.Name, count);

            var buffer = new OutputBuffer(session);
            buffer.Add("你捞到了");
            buffer.Add($"{item.Name}{(count > 1 ? $"*{count}" : string.Empty)}");
            buffer.Add($"    {item.Description} ");
            buffer.AddPair(new Dictionary<string, string>
            {
                ["稀有率"] = $"{HonorSvc.ItemRate(item)}%",
                ["售价"] = $"{item.Price} 金币",
                ["特性"] = $"{(item.Attributes == null ? "无" : string.Join(", ", item.Attributes))}"
            });
            buffer.Add($"你总共拥有该物品 {record.HonorCollections[honorName].Items[item.Name]}个");

            if (!string.IsNullOrEmpty(s))
            {
                buffer.Add(s);
            }

            if (OSPersonBuffDA.CheckBuff(session.User.ID, "钻石尘") && Rander.RandInt(100) < 50)
            {
                OSPersonDA.GoldConsume(session.User.ID, 40);
                buffer.Add("欸呀呀，你丢失了40金币(钻石尘)");
            }

            buffer.Send();
        }

        private void PrintBottle(InboxSession session, DriftBottleRecord record)
        {
            var msg = $"你捞到了一个漂流瓶 \n    “{record.Content}”\n   by 陌生人";
            session.SendBack(msg);
        }

        [ModuleEnter(Command = "扔瓶子", Description = "扔一个漂流瓶", DailyLimit = 3, SyntaxHint = "[漂流瓶内容]")]
        public bool ThrowBottle(InboxSession session, UnlimitedStr contentParam)
        {
            var content = contentParam.Data;

            if (string.IsNullOrEmpty(content))
            {
                return false;
            }

            new DriftBottleRecord
            {
                FromGroupID = session.Group?.ID,
                FromUserID = session.User.ID,
                Content = content,
                SendTime = DateTime.Now
            }.Insert();

            session.SendBack("漂流瓶已随波而去，最终将会漂到哪里呢~");
            return true;
        }

        [ModuleEnter(Command = "我的物品", Description = "查看自己的物品")]
        public bool MyItems(InboxSession session)
        {
            var query = ItemCollectionDA.Get(session.User.ID);
            if (query.TotalItemCount() == 0)
            {
                session.SendBack("你的背包空空如也~");
                return false;
            }

            var itemDic = query.HonorCollections.Where(p => p.Value.Type == HonorType.Normal)
                               .SelectMany(p => p.Value.Items)
                               .ToDictionary(p => p.Key, p => p.Value);
            var itemMsgs = HonorSvc.GetOrderedItemsStr(itemDic);
            var buffer = new OutputBuffer(session);
            buffer.Add("你收集到的物品有：");
            buffer.Add(itemMsgs.Take(PageSize));
            if (itemMsgs.Count > PageSize)
            {
                buffer.Add($"当前显示第 1/{(itemMsgs.Count - 1) / PageSize + 1}页，请使用 我的物品 [页码] 命令查看更多物品！");
            }

            buffer.Send();
            return true;
        }

        [ModuleEnter(Command = "我的物品", Description = "查看自己指定特性的物品", SyntaxHint = "[特性名]")]
        public bool MyItemsByAttr(InboxSession session, string name)
        {
            if (!PetExtent.AllAttributes.Contains(name))
            {
                session.SendBack("请输入正确的特性名！");
                return false;
            }

            var record = ItemCollectionDA.Get(session.User.ID);
            if (record.HonorCollections.IsNullOrEmpty())
            {
                session.SendBack("你的背包空空如也~");
                return false;
            }

            var items = record.HonorCollections.Where(p => p.Value.Items != null)
                              .SelectMany(p => p.Value.Items.Where
                                              (item =>
                                              {
                                                  var itemModel = HonorSvc.FindItem(item.Key);
                                                  return itemModel.Attributes != null && itemModel.Attributes.Contains(name);
                                              })).ToList();
            if (!items.Any())
            {
                session.SendBack("你没有该特性的物品！");
                return false;
            }

            var msg = $"你收集的物品中，**【{name}】** 特性的物品有：\n{string.Join(", ", items.Select(item => $"{item.Key}*{item.Value}"))}";
            session.SendBack(msg);
            return true;
        }

        [ModuleEnter(Command = "我的限定物品", Description = "查看自己的期间限定物品")]
        public bool MyLimitItems(InboxSession session)
        {
            var query = ItemCollectionDA.Get(session.User.ID);
            if (query.TotalItemCount() == 0)
            {
                session.SendBack("你的背包空空如也~");
                return false;
            }

            var itemMsgs = HonorSvc.GetOrderedItemsStr(query.HonorCollections.Where(p => p.Value.Type == HonorType.Limit)
                                                            .OrderByDescending(p => HonorSvc.FindHonor(p.Key)?.SortKey())
                                                            .SelectMany(p => p.Value.Items)
                                                            .ToDictionary(p => p.Key, p => p.Value));
            var buffer = new OutputBuffer(session);
            buffer.Add("你收集到的限定物品有：");
            buffer.Add(itemMsgs.Take(PageSize));
            if (itemMsgs.Count > PageSize)
            {
                buffer.Add($"当前显示第 1/{(itemMsgs.Count - 1) / PageSize + 1}页，请使用 我的限定物品 [页码] 命令查看更多物品！");
            }

            buffer.Send();
            return true;
        }

        [ModuleEnter(Command = "我的物品", Description = "按页码查看自己的物品", SyntaxHint = "[页码]")]
        public bool MyItems_Paged(InboxSession session, int pageNo)
        {
            var query = ItemCollectionDA.Get(session.User.ID);
            if (query.TotalItemCount() == 0)
            {
                session.SendBack("你的背包空空如也~");
                return false;
            }

            var itemMsgs = HonorSvc.GetOrderedItemsStr(query.HonorCollections.Where(p => p.Value.Type == HonorType.Normal)
                                                            .SelectMany(p => p.Value.Items)
                                                            .ToDictionary(p => p.Key, p => p.Value));
            var totalPageCount = (itemMsgs.Count - 1) / PageSize + 1;
            if (pageNo <= 0 || pageNo > totalPageCount)
            {
                session.SendBack("页码错误！");
                return false;
            }

            var buffer = new OutputBuffer(session);
            buffer.Add("该页的物品有：");
            buffer.Add(itemMsgs.Skip((pageNo - 1) * PageSize).Take(PageSize));

            buffer.Add($"当前显示第 {pageNo}/{(itemMsgs.Count - 1) / PageSize + 1}页，请使用 我的物品 [页码] 命令查看更多物品！");
            buffer.Send();
            return true;
        }

        [ModuleEnter(Command = "我的限定物品", Description = "按页码查看自己的期间限定物品", SyntaxHint = "[页码]")]
        public bool MyLimitItems_Paged(InboxSession session, int pageNo)
        {
            var query = ItemCollectionDA.Get(session.User.ID);
            if (query.TotalItemCount() == 0)
            {
                session.SendBack("你的背包空空如也~");
                return false;
            }

            var itemDic = query.HonorCollections.Where(p => p.Value.Type == HonorType.Limit)
                               .OrderByDescending(p => HonorSvc.FindHonor(p.Key)?.SortKey())
                               .SelectMany(p => p.Value.Items)
                               .ToDictionary(p => p.Key, p => p.Value);
            var itemMsgs = HonorSvc.GetOrderedItemsStr(itemDic);
            var totalPageCount = (itemMsgs.Count - 1) / PageSize + 1;
            if (pageNo <= 0 || pageNo > totalPageCount)
            {
                session.SendBack("页码错误！");
                return false;
            }

            var buffer = new OutputBuffer(session);
            buffer.Add("该页的物品有：");
            buffer.Add(itemMsgs.Skip((pageNo - 1) * PageSize).Take(PageSize));
            if (itemMsgs.Count > PageSize)
            {
                buffer.Add($"当前显示第 {pageNo}/{(itemMsgs.Count - 1) / PageSize + 1}页，请使用 我的限定物品 [页码] 命令查看更多物品！");
            }

            buffer.Send();
            return true;
        }

        [ModuleEnter(Command = "我的成就", Description = "查看自己的成就")]
        public bool MyHonors(InboxSession session)
        {
            var query = ItemCollectionDA.Get(session.User.ID);
            if (query.HonorList() == null || query.HonorList().All(p => HonorSvc.IsLimitHonor(p)))
            {
                session.SendBack("你还没有获得任何成就，继续加油吧~");
                return false;
            }

            var buffer = new OutputBuffer(session);
            buffer.AddPair(new Dictionary<string, string>
            {
                ["你获得的普通成就有"] = string.Join(", ", query.HonorList().Where(p => !HonorSvc.IsLimitHonor(p))),
                ["你获得的限定成就有"] = string.Join(", ", query.HonorList().Where(p => HonorSvc.IsLimitHonor(p)))
            });
            buffer.Send();
            return true;
        }

        [ModuleEnter(Command = "查看物品", Description = "查看某件物品的详情", SyntaxHint = "[物品名]")]
        public bool ViewItem(InboxSession session, string name)
        {
            var item = HonorSvc.FindItem(name);
            if (item == null)
            {
                session.SendBack($"未找到该物品：{name}");
                return false;
            }

            var record = ItemCollectionDA.Get(session.User.ID);
            var buffer = new OutputBuffer(session);
            buffer.Add($"{item.Name}");
            buffer.Add($"    {item.Description}");
            buffer.AddPair(new Dictionary<string, string>
            {
                ["稀有率"] = $"{HonorSvc.ItemRate(item)}%",
                ["价格"] = $"{HonorSvc.GetItemPrice(item, session.User.ID).CurencyFormat()}",
                ["特性"] = $"{(item.Attributes == null ? "无" : string.Join(",", item.Attributes))}",
                ["可解锁成就"] = $"{HonorSvc.FindHonorFullName(item.Name)}",
                ["你拥有该物品"] = $"{record.GetCount(item.Name)}个"
            });
            buffer.Send();
            return true;
        }

        [ModuleEnter(Command = "查看成就", Description = "查看某个成就的详情", SyntaxHint = "[成就名]")]
        public bool ViewHonor(InboxSession session, string name)
        {
            var honor = HonorSvc.FindHonor(name);
            if (honor == null)
            {
                session.SendBack($"未找到该成就：{name}");
                return false;
            }

            var record = ItemCollectionDA.Get(session.User.ID);
            var items = honor.Items.Select(h => $"{h.Name}*{record.GetCount(h.Name)}");
            var itemsMsg = string.Join(", ", items);
            var msg = $"解锁成就 【{honor.FullName()}】 需要集齐：{itemsMsg}";
            session.SendBack(msg);
            return true;
        }

        [ModuleEnter(Command = "限定物品收集报告", Description = "获取当月限定物品的收集报告")]
        public bool LimitItemReport(InboxSession session)
        {
            var LimitHonor = HonorSvc.HonorList.First(h => h.IsCurLimit());
            var LimitItemsNames = LimitHonor.Items.Select(i => i.Name);

            var allRecord = ItemCollectionDA.GetByHonor(LimitHonor.Name);
            var itemDic = LimitItemsNames.ToDictionary(p => p, _ => 0);

            foreach (var colle in allRecord.Select(record => record.HonorCollections[LimitHonor.Name]))
            {
                foreach (var (key, value) in colle.Items)
                {
                    itemDic[key] += value;
                }
            }

            var honorCount = allRecord.Count(r => r.HonorList() != null && r.HonorList().Contains(LimitHonor.Name));

            var buffer = new OutputBuffer(session);
            buffer.Add("限定物品收集情况：");
            buffer.AddPair(itemDic.ToDictionary(p => p.Key, p => p.Value.ToString()));
            buffer.Add($"共有 **{honorCount}** 人达成了本月限定成就");
            buffer.Send();
            return true;
        }

        [ModuleEnter(Command = "今日捞瓶子统计", Description = "查看今日捞瓶子情况统计")]
        public bool TodayDriftAnalyze(InboxSession session)
        {
            var todayRec = DriftBottleAnalyzeDA.GetToday();
            if (todayRec.ItemDic.IsNullOrEmpty())
            {
                session.SendBack("尚未有人捞到瓶子！");
                return false;
            }

            var modelDic = todayRec.ItemDic.ToDictionary(p => HonorSvc.FindItem(p.Key), p => p.Value);

            var buffer = new OutputBuffer(session);
            buffer.Add("今日捞瓶子统计");
            buffer.AddPair(new Dictionary<string, string>
            {
                ["总次数"] = $"{todayRec.ItemDic.Sum(p => p.Value)}",
                ["总价值"] = $"{modelDic.Sum(p => p.Key.Price * p.Value)}"
            });
            buffer.Send();
            return true;
        }

        [ModuleEnter(Command = "物品统计", Description = "查看指定物品的数量", SyntaxHint = "[物品名]")]
        public bool ItemCount(InboxSession session, string name)
        {
            if (HonorSvc.FindItem(name) == null)
            {
                session.SendBack("未查找到相关物品！");
                return false;
            }

            var honor = HonorSvc.FindHonorName(name);

            var recs = ItemCollectionDA.GetByHonorAndItem(honor, name);

            var count = recs.Sum(r => r.HonorCollections[honor].Items[name]);
            session.SendBack($"当前**{name}**被收集了{count}个");
            return true;
        }

        [ModuleEnter(Command = "我缺少的物品", Description = "查看自己缺少的物品（仅当缺少的物品少于20件时显示详情信息）")]
        public bool MyLackItems(InboxSession session)
        {
            var itemColle = ItemCollectionDA.Get(session.User.ID);
            var allColleItems = itemColle.HonorCollections.SelectMany(p => p.Value.Items).Select(p => p.Key);
            var allItems = HonorSvc.HonorList.Where(h => !h.IsLimit).SelectMany(h => h.Items);

            var lackItems = allItems.Where(p => !allColleItems.Contains(p.Name)).ToList();
            if (lackItems.IsNullOrEmpty())
            {
                session.SendBack("恭喜你已经集齐了所有物品！");
                return false;
            }

            var msg = $"你总共缺少{lackItems.Count}件物品\n";
            msg += lackItems.Count <= 20 ? string.Join(", ", lackItems.Select(p => p.Name)) : "你缺少的物品太多啦！这里就不一一列举了！";

            session.SendBack(msg);
            return true;
        }
    }
}